package currency

import (
	c "bbtradeByGo/common"
	"bbtradeByGo/fetch"
	cl "bbtradeByGo/model/currency"
	"bbtradeByGo/pkg/email"
	"bbtradeByGo/pkg/gredis"
	"bbtradeByGo/pkg/logging"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gomodule/redigo/redis"
	"reflect"
	"strconv"
	"time"
)


//Currency 函数入口
func Currency() error{
	ids := make([]interface{},0)
	//1.获取基础货币列表
	baseList, err := cl.CurrencyList(&cl.Condition{
		IsBasic:1,
		Fields:"currency_name,id,currency_type,is_primary,is_basic,currency_img",
	})
	if err != nil{return errors.New("cl.CurrencyList:"+err.Error())}
	for _, g := range baseList {
		//2.交易对列表
		Trade, err := cl.CurrencyList(&cl.Condition{
			IsPair:true,
			Bcid:   g.Id,
			Status: 1,
			Fields: "price_base, a.dpc, a.npc, a.buy_pdg, a.sell_pdg, a.buy_min, a.sell_min, currency_name,id,currency_type,is_primary,is_basic,currency_img",
		})
		if err != nil{return errors.New("Trade:"+err.Error())}
		g.Trade = Trade
		for _, v := range g.Trade{
			 //3.24小时交易统计
             count, err := cl.TradeCount24(g.Id, v.Id)
             if err != nil{return errors.New("TradeCount24:"+err.Error())}
             priceNew, err := cl.TradeNew(g.Id, v.Id)
			 if err != nil{return errors.New("TradeNew:"+err.Error())}
             open, err := cl.TradeCount24Open(g.Id, v.Id)
			 if err != nil{return errors.New("TradeCount24Open: " + err.Error())}
             if len(count) > 0 && count[0].PriceMax != 0{
				 CountMoreThanZero(v, count, priceNew, open)
			 }else{
				 CountLessThanZero(v, priceNew)
			 }
		}
		key := fmt.Sprintf("%s%d","currency:base:",g.Id)

		ReflectUtil(key, g)
		ids = append(ids, g.Id)
		// 获取所有币种的信息
		if err := AllCoin(ids); err != nil{return errors.New("AllCoin:"+err.Error())}
	}
	return nil
}

//CountMoreThanZero 统计数大于0
func CountMoreThanZero(v *cl.BaseList,  count, priceNew, open []*cl.Count) {
		v.PriceMax = count[0].PriceMaxRepeat
		v.PriceMin = count[0].PriceMinRepeat
		if len(priceNew) > 0 {
			v.PriceNew = priceNew[0].PriceNewRepeat
		}else {
			v.PriceNew = 0
		}
		v.PriceOpen  = open[0].PriceOpenRepeat
		v.Amount     = count[0].Amount
		v.BaseAmount = count[0].BaseAmountRepeat
		v.Increase   = v.PriceOpen
		if v.PriceOpen == 0 {
			v.Increase = 0
		}else{
			logging.Info(" v.Trade[i].Increase value",  v.Increase)
			v.Increase = (v.PriceNew - v.PriceOpen) * 100 / v.PriceOpen
		}
}

//CountLessThanZero 统计数小于0
func CountLessThanZero(v *cl.BaseList,  priceNew []*cl.Count)  {
	var preNew float64
	var preMax float64
	var preMin float64
	if len(priceNew) > 0 {preNew = priceNew[0].PriceNewRepeat
	}else{preNew = v.PriceBase}

	if preNew > v.PriceBase{preMin = v.PriceBase
	}else{preMin = preNew}

	if preNew < v.PriceBase{preMax = v.PriceBase
	}else { preMax = preNew}

	v.PriceNew    = preNew
	v.PriceMax    = preMax
	v.PriceMin    = preMin
	v.PriceOpen   = preNew
	v.Amount      = 0
	v.BaseAmount  = 0
	v.Increase    = 0
}

// AllCoin 所有币种
func AllCoin(ids []interface{}) error{
	//2.先清洗基础币集合
	isList := gredis.Exists("currency:base:list")
	if isList == true{
		_, err := gredis.Delete("currency:base:list")
		if err != nil{
			return err
		}
	}
	for _, v := range ids{
		gredis.LPush("currency:base:list", v)
	}
	//获取所有币种信息
	allList, err := cl.CurrencyList(&cl.Condition{
		Fields: "*",
	})
	if err != nil{
		return err
	}
	for _,v := range allList{
		key := fmt.Sprintf("%s%d", "currency:all:",v.Id)
		ReflectUtil(key, v)
	}
	return nil
}

//ReflectUtil 反射工具
func ReflectUtil(key string, x *cl.BaseList) {
	ff := reflect.TypeOf(*x)
	vf := reflect.ValueOf(x).Elem()
	count := vf.NumField()
	for i := 0; i < count; i++ {
		f := vf.Field(i)
		switch f.Kind() {
		case reflect.Int:
			gredis.HSet(key, c.Mapper(ff.Field(i).Name), f.Interface())
		case reflect.Float64:
			gredis.HSet(key, c.Mapper(ff.Field(i).Name), f.Interface())
		case reflect.Slice:
			gredis.HSet(key, c.Mapper(ff.Field(i).Name), f.Interface())
		case reflect.String:
			gredis.HSet(key, c.Mapper(ff.Field(i).Name), f.Interface())
		}
	}
}

//Price 交易对下面的价格
func Price(){
	// 获取USDT 交易对下面的价格
	// USDT currency_id 一定要等于1
	// ！！！ 基础币一定要与USDT对应

	gredis.HSet("currency:price:list", 1,1)
	SetPrice(1)

	//获取其他所有价格
	alls, err := redis.Ints(gredis.LRange("currency:base:list", 0, -1))
	if err != nil{
		email.SendMail("service.currency.price", err.Error())
		logging.Error("service.currency.currency.go Price err: \n",err)
	}
	for _, v := range alls{
		if v != 1{
			SetPrice(v)
		}
	}

	//美元和人民币的汇率问题
    USD, err := fetch.Fetch("https://api.coinbase.com/v2/prices/BTC-USD/spot")
    if err != nil{
		email.SendMail("service.currency.price", err.Error())
		logging.Error("service.currency.currency.go Price USD err: \n",err)
	}
    value1 := fetch.Rate{}
    err = json.Unmarshal(USD, &value1)
    if err != nil{
		email.SendMail("service.currency.price", err.Error())
		logging.Error("service.currency.currency.go Price USD json.Unmarsha err: \n",err)
	}
    CNY, err := fetch.Fetch("https://api.coinbase.com/v2/prices/BTC-CNY/spot")
	if err != nil{
		email.SendMail("service.currency.price", err.Error())
		logging.Error("service.currency.currency.go Price CNY err: \n",err)
	}
	value2 := fetch.Rate{}
    err = json.Unmarshal(CNY, &value2)
    if err != nil{
		email.SendMail("service.currency.price", err.Error())
		logging.Error("service.currency.currency.go Price CNY json.Unmarsha err: \n",err)
	}
	usd, _ := strconv.ParseFloat(value1.Data.Amount, 64)
    cny, _ := strconv.ParseFloat(value2.Data.Amount, 64)

    rate := cny/usd
    logging.Info("rate:", rate)
    err = gredis.Set("currency:price:rate", rate, time.Now().Unix())
    if err != nil{
		email.SendMail("service.currency.price", err.Error())
		logging.Error("service.currency.currency.go Price gredis.Set err: \n",err)
	}
}

//SetPrice 设置价格
func SetPrice(cid int){
	key := fmt.Sprintf("%s%d", "currency:base:",cid)
	lists, err := redis.Bytes(gredis.HGet(key, "trade"))
	if lists == nil{
		return
	}
	vs := []cl.PriceList{}
	err = json.Unmarshal(lists, &vs)

	if err != nil{
		email.SendMail("service.currency.setprice", err.Error())
		logging.Error("service.currency SetPrice list err: \n",err)
	}

	cID, err  := redis.Int(gredis.HGet(key, "id"))

	if err != nil{
		email.SendMail("service.currency.setprice", err.Error())
		logging.Error("service.currency SetPrice cID err: \n",err)
	}

	for _,v := range vs{
		priceParent,err := redis.Float64(gredis.HGet("currency:price:list", cID))
		if err != nil{
			email.SendMail("service.currency.setprice", err.Error())
			logging.Error("service.currency SetPrice priceParent err: \n",err)
		}
		logging.Info("currency:price:list.PriceNew:", v.PriceNew)
		gredis.HSet("currency:price:list", v.Id, v.PriceNew * priceParent)
	}
}

